﻿using System;

namespace Lesson6_泛型约束
{
    #region 知识回顾 
    //泛型类
    class TestClass<T, U>
    {
        public T t;
        public U u;

        public U TestFun(T t)//普通函数 因为他是跟着泛型类来变换类型参数的
        {
            return default(U);//返回各种类型的默认值
        }

        //泛型函数
        public  V TestFun<K, V>(K k)
        {
            return default(V);
        }
    }
    #endregion

    #region 知识点一 什么是泛型约束
    //让泛型的类型有一定的限制
    //关键字：where
    //泛型约束一共有6种
    //1.值类型                               where 泛型字母: struct
    //2.引用类型                             where 泛型字母: class
    //3.存在无参公共构造函数                 where 泛型字母: new()
    //4.某个类本身或者其派生类               where 泛型字母:类名
    //5.某个接口的派生类型                   where 泛型字母:接口名
    //6.另一个泛型类型本身或者派生类型       where 泛型字母:另一个泛型字母

    //总结: where 泛型字母:（约束类型）
    #region 知识点二 各泛型约束讲解

    #region 值类型约束
    class Test1<T> where T:struct//添加了值类型约束的泛型类
    {
        public T value;

        public void TestFun<K>() where K: struct//添加了值类型约束的泛型方法
        {

        }
    }
    #endregion

    #region 引用类型约束
    class Test2<T> where T : class //添加了引用类型约束的泛型类
    {
        public T value;

        public void TestFun<K>() where K : class//添加了引用类型约束的泛型方法
        {

        }
    }
    #endregion

    #region 公共无参构造约束
    class Test3<T> where T : new() //表明了这个T类型必须是一个公共的无参构造函数
    {
        public T value;

        public void TestFun<K>() where K : new()//添加了无参公共构造函数约束的泛型方法
        {

        }
    }
    #endregion

    #endregion

    #region 知识点三 约束的组合使用

    #endregion

    #region  知识点四 多个泛型有约束

    #endregion

    #endregion

    class Test1//一个类里面默认有一个无参构造函数
    {

    }

    class Test2 
    {
        public Test2(int a)//如果在类里面创建了一个有参构造函数，那么他将会被顶掉
        {

        }
    }
    internal class Program
    {  
        static void Main(string[] args)
        {
            Console.WriteLine("泛型约束");

            TestClass<string,int> t = new TestClass<string,int>();//泛型类
            t.t = "11234asdc";
            t.u = 123;

            t.TestFun("1231");//普通函数调用
            t.TestFun<bool, float>(true);//泛型函数调用

            //值类型约束
            Test1<float> t1 = new Test1<float>();//这个泛型类只能填值类型 不然会报空
            t1.TestFun<uint>();//这个泛型方法只能填值类型 不然会报空

            //引用类型约束
            Test2<string> t2 = new Test2<string>();//这个泛型类只能填引用类型 不然会报空
            //值类型约束泛型类也是引用类型
            t2.TestFun<Test1<float>>();//这个泛型方法只能填引用类型 不然会报空

            Test3<Test1> t3 = new Test3<Test1>();//公共无参构造函数

        }
    }
}
